#include "../test_type.h"
#include "../../src/tools/ShareApi.h"
#include "../../src/thread/SharedPtr.h"
#include <iostream>

using namespace LibTools;
using namespace std;

#ifdef WIN32
static unsigned _stdcall windows_start_address(void* arg)
{
	cout << "test windows dll" << endl;
	return 0;
}
#elif defined(LINUX)
static void* _stdcall linux_start_routine(void* arg)
{
	cout << "test linux dll" << endl;
	return 0;
}
#endif

#ifdef TEST_DLL
int main()
{
	ShareApi::PrintDumpInfo();
#ifdef WIN32
	typedef HANDLE (WINAPI *My_CreateThread)(
		_In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes,
		_In_ SIZE_T dwStackSize,
		_In_ LPTHREAD_START_ROUTINE lpStartAddress,
		_In_opt_ __drv_aliasesMem LPVOID lpParameter,
		_In_ DWORD dwCreationFlags,
		_Out_opt_ LPDWORD lpThreadId
		);
	HANDLE dll = ShareApi::LoadDll(TEXT("Kernel32.dll"));
	if (dll)
	{
		My_CreateThread func = (My_CreateThread)ShareApi::LoadSymbol(dll, TEXT("CreateThread"));
		if (func) {
			ShareApi::CloseDll(dll);
			func(NULL, 0, (LPTHREAD_START_ROUTINE)&windows_start_address, NullPtr, 0, NullPtr);
		}
		else
		{
			SharedPtr<TCHAR> ec(ShareApi::Global_GetLastError(), &ShareApi::Global_FreeMem);
			cout << ec.Get() << endl;
		}
	}
	else
	{
		SharedPtr<TCHAR> ec(ShareApi::Global_GetLastError(), &ShareApi::Global_FreeMem);
		cout << ec.Get() << endl;
	}
#elif defined(LINUX)
	HANDLE dll = ShareApi::LoadDll("libm.so");
	if (dll)
	{
		double (*cosine)(double);
		*(void **)(&cosine) = ShareApi::LoadSymbol(dll, "cos");
		if (cosine){
			printf("%f\n", (*cosine)(2.0));
		}
		else
		{
			SharedPtr<TCHAR> ec(ShareApi::Global_GetLastError(), &ShareApi::Global_FreeMem);
			cout << ec.Get() << endl;
		}
	}
	else
	{
		SharedPtr<TCHAR> ec(ShareApi::Global_GetLastError(), &ShareApi::Global_FreeMem);
		cout << ec.Get() << endl;
	}
#endif

	ShareApi::Sleep(1000);
	ShareApi::CloseDll(dll);
	return 0;
}

#endif // TEST_DLL